package com.github.anastr.speedviewlib;

import com.github.anastr.speedviewlib.components.Indicators.TriangleIndicator;
import com.github.anastr.speedviewlib.util.AttrSetUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

/**
 * this Library build By Anas Altair
 * see it on <a href="https://github.com/anastr/SpeedView">GitHub</a>
 */
public class AwesomeSpeedometer extends Speedometer {

    private Path markPath = new Path(),
            trianglesPath = new Path();
    private Paint markPaint = new Paint(),
            ringPaint = new Paint(),
            trianglesPaint = new Paint();
    private RectFloat speedometerRect = new RectFloat();

    private int speedometerColor = 0xff00e6e6;

    public AwesomeSpeedometer(Context context) {
        this(context, null);
    }

    public AwesomeSpeedometer(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public AwesomeSpeedometer(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
        initAttributeSet(context, attrSet);
    }

    @Override
    protected void defaultGaugeValues() {
        super.setTextColor(0xffffc260);
        super.setSpeedTextColor(0xFFFFFFFF);
        super.setUnitTextColor(0xFFFFFFFF);
        super.setTextTypeface(new Font.Builder("myfont").setWeight(Font.BOLD).build());
        super.setSpeedTextPosition(Position.CENTER);
        super.setUnitUnderSpeedText(true);
    }


    @Override
    protected void defaultSpeedometerValues() {
        super.setIndicator(new TriangleIndicator(getContext())
                .setIndicatorWidth(dpTOpx(25f))
                .setIndicatorColor(0xff00e6e6));
        super.setStartEndDegree(135, 135 + 320);
        super.setSpeedometerWidth(dpTOpx(60f));
        super.setBackgroundCircleColor(0xff212121);
        super.setTickNumber(9);
        super.setTickPadding(0);
    }

    private void init() {
        markPaint.setAntiAlias(true);
        ringPaint.setAntiAlias(true);
        trianglesPaint.setAntiAlias(true);
        markPaint.setStyle(Paint.Style.STROKE_STYLE);
        textPaint.setTextAlign(TextAlignment.CENTER);
        ringPaint.setStyle(Paint.Style.STROKE_STYLE);
        trianglesPaint.setColor(new Color(0xff3949ab));
    }


    private void initAttributeSet(Context context, AttrSet attrs) {
        if (attrs == null)
            return;
        speedometerColor = AttrSetUtils.getAttrSetColorInt(attrs, "sv_speedometerColor", speedometerColor);
        trianglesPaint.setColor(new Color(AttrSetUtils.getAttrSetColorInt(attrs, "sv_trianglesColor", trianglesPaint.getColor().getValue())));
    }

    @Override
    protected void onSizeChange(int w, int h, int oldW, int oldH) {
        super.onSizeChange(w, h, oldW, oldH);

        updateGradient();
        updateBackgroundBitmap();
    }

    private void updateGradient() {
        float stop = (getSizePa() * .5f - getSpeedometerWidth()) / (getSizePa() * .5f);
        float stop2 = stop + ((1f - stop) * .1f);
        float stop3 = stop + ((1f - stop) * .36f);
        float stop4 = stop + ((1f - stop) * .64f);
        float stop5 = stop + ((1f - stop) * .9f);
        Color[] colors = new Color[]{new Color(getBackgroundCircleColor()), new Color(speedometerColor), new Color(getBackgroundCircleColor())
                , new Color(getBackgroundCircleColor()), new Color(speedometerColor), new Color(speedometerColor)};
        Shader radialGradient = new RadialShader(new Point(getSize() * .5f, getSize() * .5f), getSizePa() * .5f, new float[]{stop, stop2, stop3, stop4, stop5, 1f}, colors, Shader.TileMode.CLAMP_TILEMODE);
        ringPaint.setShader(radialGradient, Paint.ShaderType.RADIAL_SHADER);
    }

    private void initDraw() {
        ringPaint.setStrokeWidth(getSpeedometerWidth());
        markPaint.setColor(new Color(getMarkColor()));
    }

    @Override
    public void onDrawComponent(Component component, Canvas canvas) {
        super.onDrawComponent(component, canvas);

        drawSpeedUnitText(canvas);
        drawIndicator(canvas);
        drawNotes(canvas);
    }

    @Override
    protected void updateBackgroundBitmap() {
        Canvas c = createBackgroundBitmapCanvas();
        initDraw();

        float markH = getViewSizePa() / 22f;
        markPath.reset();
        markPath.moveTo(getSize() * .5f, getCustomPadding());
        markPath.lineTo(getSize() * .5f, markH + getCustomPadding());
        markPaint.setStrokeWidth(markH / 5f);

        float triangleHeight = getViewSizePa() / 20f;
        setInitTickPadding(triangleHeight);

        trianglesPath.reset();
        trianglesPath.moveTo(getSize() * .5f, getCustomPadding() + getViewSizePa() / 20f);
        float triangleWidth = getViewSize() / 20f;
        trianglesPath.lineTo(getSize() * .5f - triangleWidth / 2f, getCustomPadding());
        trianglesPath.lineTo(getSize() * .5f + triangleWidth / 2f, getCustomPadding());

        float risk = getSpeedometerWidth() * .5f + getCustomPadding();
        speedometerRect = new RectFloat(risk, risk, getSize() - risk, getSize() - risk);
        c.drawArc(speedometerRect, new Arc(0f, 360f, false), ringPaint);

        drawMarks(c);
        drawTicks(c);
    }


    protected void drawMarks(Canvas c) {
        for (int i = 0; i < getTickNumber(); i++) {
            float d = getDegreeAtSpeed(getTicks().get(i)) + 90f;
            c.save();
            c.rotate(d, getSize() * .5f, getSize() * .5f);

            c.drawPath(trianglesPath, trianglesPaint);
            if (i + 1 != getTickNumber()) {
                c.save();
                float d2 = getDegreeAtSpeed(getTicks().get(i + 1)) + 90f;
                float eachDegree = d2 - d;
                for (int j = 1; j < 10; j++) {
                    c.rotate(eachDegree * .1f, getSize() * .5f, getSize() * .5f);
                    if (j == 5)
                        markPaint.setStrokeWidth(getSize() / 22f / 5);
                    else
                        markPaint.setStrokeWidth(getSize() / 22f / 9);
                    c.drawPath(markPath, markPaint);
                }
                c.restore();
            }
            c.restore();
        }
    }

    @Override
    public void setSpeedometerWidth(float speedometerWidth) {
        super.setSpeedometerWidth(speedometerWidth);
        float risk = speedometerWidth * .5f;
        speedometerRect = new RectFloat(risk, risk, getSize() - risk, getSize() - risk);
        updateGradient();
        updateBackgroundBitmap();
        invalidate();
    }

    public int getSpeedometerColor() {
        return speedometerColor;
    }

    public void setSpeedometerColor(int speedometerColor) {
        this.speedometerColor = speedometerColor;
        updateGradient();
        updateBackgroundBitmap();
        invalidate();
    }

    public int getTrianglesColor() {
        return trianglesPaint.getColor().getValue();
    }

    public void setTrianglesColor(int trianglesColor) {
        trianglesPaint.setColor(new Color(trianglesColor));
        updateBackgroundBitmap();
        invalidate();
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @return {@code Color.TRANSPARENT} always.
     */
    @Deprecated
    @Override
    public int getLowSpeedColor() {
        return 0;
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @param lowSpeedColor nothing.
     */
    @Deprecated
    @Override
    public void setLowSpeedColor(int lowSpeedColor) {
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @return {@code Color.TRANSPARENT} always.
     */
    @Deprecated
    @Override
    public int getMediumSpeedColor() {
        return 0;
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @param mediumSpeedColor nothing.
     */
    @Deprecated
    @Override
    public void setMediumSpeedColor(int mediumSpeedColor) {
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @return {@code Color.TRANSPARENT} always.
     */
    @Deprecated
    @Override
    public int getHighSpeedColor() {
        return 0;
    }

    /**
     * this Speedometer doesn't use this method.
     *
     * @param highSpeedColor nothing.
     */
    @Deprecated
    @Override
    public void setHighSpeedColor(int highSpeedColor) {
    }
}
